package com.zk.util;

/**
 * @author ZHAIKE
 * @date 2024/10/17 15:21
 */

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * file工具类
 */
public class FileUtil {

    private static int DEFAULT_BUFFER_SIZE = 4096;

    /**
     * 读取文件内容
     */
    public static String readFile(String filePath) throws IOException {
        File file = new File(filePath);
        StringBuilder sb = new StringBuilder();

        try (InputStream in = new FileInputStream(file)) {
            // 一次读多个字节
            byte[] bytes = new byte[1024];
            int i;
            while ((i = in.read(bytes)) != -1) {
                String str = new String(bytes, 0, i);
                sb.append(str);
            }
        }

        return sb.toString();
    }

    /**
     * 删除文件
     */
    public static boolean deleteFile(String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            return false;
        }

        File file = new File(filePath);
        if (file.isDirectory() || !file.exists()) {
            return false;
        }
        return file.delete();
    }

    /**
     * 删除文件夹
     *
     * @param isDeleteSub 是否删除子文件夹
     */
    public static boolean deleteDir(File dir, boolean isDeleteSub) {
        if (dir == null || dir.isFile()) {
            return false;
        }
        File[] files = dir.listFiles();
        if (files != null && isDeleteSub) {
            for (File file : files) {
                if (file.exists() && file.isFile()) {
                    return file.delete();
                } else {
                    return deleteDir(file, true);
                }
            }
        }
        return dir.delete();
    }

    /**
     * 复制文件
     */
    public static void copy(String sourcePath, String targetPath) throws IOException {
        copyBase(sourcePath, targetPath, false);
    }

    /**
     * 复制文件 追加
     */
    public static void copyAppend(String sourcePath, String targetPath) throws IOException {
        copyBase(sourcePath, targetPath, true);
    }

    private static void copyBase(String sourcePath, String targetPath, boolean isAppend)
            throws IOException {
        if (StringUtils.isAnyEmpty(sourcePath, targetPath)) {
            return;
        }
        try (InputStream in =
                     new BufferedInputStream(new FileInputStream(sourcePath), DEFAULT_BUFFER_SIZE)) {
            try (OutputStream out =
                         new BufferedOutputStream(
                                 new FileOutputStream(targetPath, isAppend), DEFAULT_BUFFER_SIZE)) {
                byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
                int len;
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            }
        }
    }

    /**
     * ftp上传文件
     *
     * @param filePath   本地文件路径，包含文件名
     * @param remotePath 上传到FTP的路径
     * @return 成功/失败
     */
    public boolean uploadByFtp(
            String filePath, String remotePath, String host, int port, String userName, String password)
            throws IOException {
        if (StringUtils.isAnyEmpty(filePath, remotePath, host, userName, password)) {
            return false;
        }
        File file = new File(filePath);
        if (!file.exists()) {
            return false;
        }
        FTPClient ftp = initFTPClient(remotePath, host, port, userName, password);
        if (ftp == null) {
            return false;
        }
        try (FileInputStream inputStream = new FileInputStream(file)) {
            ftp.storeFile(file.getName(), inputStream);
        }

        ftp.logout();
        return true;
    }

    /**
     * ftp下载文件。
     *
     * @param remotePath FTP服务器上的相对路径
     * @param fileName   要下载的文件名
     * @param localPath  下载后保存到本地的路径
     * @return 成功/失败
     */
    public boolean downloadByFtp(
            String remotePath,
            String fileName,
            String localPath,
            String host,
            int port,
            String userName,
            String password)
            throws IOException {
        if (StringUtils.isAnyEmpty(remotePath, fileName, localPath, host, userName, password)) {
            return false;
        }
        FTPClient ftp = initFTPClient(remotePath, host, port, userName, password);
        if (ftp == null) {
            return false;
        }
        FTPFile[] fs = ftp.listFiles();
        FTPFile ff;
        for (FTPFile f : fs) {
            ff = f;
            if (null != ff && null != ff.getName() && ff.getName().equals(fileName)) {
                File localFile = new File(localPath + "/" + ff.getName());
                try (OutputStream is = new FileOutputStream(localFile)) {
                    ftp.retrieveFile(ff.getName(), is);
                }
            }
        }
        ftp.logout();
        return true;
    }

    /**
     * 从ftp服务器列出指定文件夹下文件名列表。
     *
     * @param remotePath FTP服务器上的相对路径
     */
    public List<String> getFileNamesByFtp(
            String remotePath, String host, int port, String userName, String password)
            throws IOException {
        // 目录列表记录
        List<String> fileNames = new ArrayList<>();
        FTPClient ftp = initFTPClient(remotePath, host, port, userName, password);
        if (ftp == null) {
            return null;
        }
        FTPFile[] fs = ftp.listFiles();
        for (FTPFile file : fs) {
            fileNames.add(file.getName());
        }
        ftp.logout();
        return fileNames;
    }

    /**
     * 初始化FTPClient, 登录及切换目录
     */
    private static FTPClient initFTPClient(
            String remotePath, String host, int port, String userName, String password)
            throws IOException {
        FTPClient ftp = new FTPClient();
        ftp.connect(host, port);
        // 登录
        ftp.login(userName, password);
        int reply = ftp.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            ftp.disconnect();
            return null;
        }
        ftp.changeWorkingDirectory(remotePath);
        return ftp;
    }
}

